using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace Assignment4_Network
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class InputProcessor : Microsoft.Xna.Framework.GameComponent
    {

        public const int maxPlayer = 4;

        private MouseState currentMouseState;
        private MouseState lastMouseState;

        private KeyboardState currentKeyboardState;
        private KeyboardState lastKeyboardState;

        private GamePadState[] currentGamePadState;
        private GamePadState[] lastGamePadState;

        public bool[] gamePadConnected;

        public InputProcessor(Game game)
            : base(game)
        {
            // TODO: Construct any child components here
            currentMouseState = new MouseState();
            lastMouseState = new MouseState();

            currentKeyboardState = new KeyboardState();
            lastKeyboardState = new KeyboardState();

            currentGamePadState = new GamePadState[maxPlayer];
            lastGamePadState = new GamePadState[maxPlayer];

            gamePadConnected = new bool[maxPlayer];
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here

            base.Initialize();
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here  

            lastMouseState = currentMouseState;
            currentMouseState = Mouse.GetState();

            lastKeyboardState = currentKeyboardState;
            currentKeyboardState = Keyboard.GetState();

            for (int i = 0; i < maxPlayer; i++)
            {                
                lastGamePadState[i] = currentGamePadState[i];
                currentGamePadState[i] = GamePad.GetState((PlayerIndex)i);

                if (currentGamePadState[i].IsConnected)
                    gamePadConnected[i] = true;
            }

            base.Update(gameTime);
        }
        
        //Keyboard
        public bool isKeyDown(Keys key)
        {
            return currentKeyboardState.IsKeyDown(key);
        }

        public bool isKeyPressed(Keys key)
        {
            return (lastKeyboardState.IsKeyUp(key) && currentKeyboardState.IsKeyDown(key));
        }

        //GamePad
        public bool isButtonDown(Buttons button, PlayerIndex i)
        {
            return currentGamePadState[(int)i].IsButtonDown(button);
        }

        public bool isButtonPressed(Buttons button, PlayerIndex i)
        {
            return (lastGamePadState[(int)i].IsButtonDown(button) && currentGamePadState[(int)i].IsButtonUp(button));
        }

        public bool isLeftThumbstickMoveLeft(PlayerIndex i)
        {
            return (currentGamePadState[(int)i].ThumbSticks.Left.X) < 0;
        }

        public bool isLeftThumbstickMoveRight(PlayerIndex i)
        {
            return (currentGamePadState[(int)i].ThumbSticks.Left.X) > 0;
        }

        public bool isLeftThumbstickMoveUp(PlayerIndex i)
        {
            return (currentGamePadState[(int)i].ThumbSticks.Left.Y) > 0;
        }

        public bool isLeftThumbstickMoveDown(PlayerIndex i)
        {
            return (currentGamePadState[(int)i].ThumbSticks.Left.Y) < 0;
        }

        public bool isDpadLeftDown(PlayerIndex i)
        {
            return currentGamePadState[(int)i].DPad.Left == ButtonState.Pressed;
        }

        public bool isDpadLeftPressed(PlayerIndex i)
        {
            return (currentGamePadState[(int)i].DPad.Left == ButtonState.Pressed && lastGamePadState[(int)i].DPad.Left == ButtonState.Released);
        }

        public bool isDpadRightDown(PlayerIndex i)
        {
            return currentGamePadState[(int)i].DPad.Right == ButtonState.Pressed;
        }

        public bool isDpadRightPressed(PlayerIndex i)
        {
            return (currentGamePadState[(int)i].DPad.Right == ButtonState.Pressed && lastGamePadState[(int)i].DPad.Right == ButtonState.Released);
        }

        public bool isDpadUpDown(PlayerIndex i)
        {
            return currentGamePadState[(int)i].DPad.Up == ButtonState.Pressed;
        }

        public bool isDpadUpPressed(PlayerIndex i)
        {
            return (currentGamePadState[(int)i].DPad.Up == ButtonState.Pressed && lastGamePadState[(int)i].DPad.Up == ButtonState.Released);
        }

        public bool isDpadDownDown(PlayerIndex i)
        {
            return currentGamePadState[(int)i].DPad.Down == ButtonState.Pressed;
        }

        public bool isDpadDownPressed(PlayerIndex i)
        {
            return (currentGamePadState[(int)i].DPad.Down == ButtonState.Pressed && lastGamePadState[(int)i].DPad.Down == ButtonState.Released);
        }

        public Vector2 getRightThumbstickValue(PlayerIndex i)
        {
            return currentGamePadState[(int)i].ThumbSticks.Right;
        }

        public Vector2 getLeftThumbstickValue(PlayerIndex i)
        {
            return currentGamePadState[(int)i].ThumbSticks.Left;
        }

        //Mouse
        public bool isLeftMouseDown()
        {
            return currentMouseState.LeftButton == ButtonState.Pressed;
        }

        public bool isLeftMouseClicked()
        {
            return (currentMouseState.LeftButton == ButtonState.Released && lastMouseState.LeftButton == ButtonState.Pressed);
        }

        public bool isRightMouseDown()
        {
            return currentMouseState.RightButton == ButtonState.Pressed;
        }

        public bool isRightMouseClicked()
        {
            return (currentMouseState.RightButton == ButtonState.Released && lastMouseState.RightButton == ButtonState.Pressed);
        }

        public bool isMiddleMouseDown()
        {
            return currentMouseState.MiddleButton == ButtonState.Pressed;
        }

        public bool isMiddleMouseClicked()
        {
            return (currentMouseState.MiddleButton == ButtonState.Released && lastMouseState.MiddleButton == ButtonState.Pressed);
        }
    }
}
